package com.zaoniao.enstudy.infracore.exception;

import com.zaoniao.enstudy.infracore.web.BaseResponse;
import com.zaoniao.enstudy.infracore.web.CommonError;
import com.zaoniao.enstudy.infracore.web.DataResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.AccessDeniedException;
import java.util.List;

/**
 * 自定义异常捕获.
 *
 * @author 斌~
 * @version 1.0
 * @date 2020/10/10 12:13 上午
 */
@RestControllerAdvice
@Slf4j
public class CustomExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomExceptionHandler.class);

    /**
     * 文件上传异常.
     *
     * @param e -
     * @return -
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public BaseResponse handlerMaxUploadFile(MaxUploadSizeExceededException e) {
        LOGGER.error("文件上传异常:", e);
        return DataResponse.errorMsg("文件上传不能大于500KB");
    }

    /**
     * 未知异常.
     */
    @ExceptionHandler(value = Exception.class)
    public BaseResponse exceptionHandler(HttpServletRequest request, Exception e) {
        LOGGER.error("【{}】发生未知异常:", request.getRequestURL(), e);
        return DataResponse.fail(CommonError.UnExpected);
    }

    // 参数异常.
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request,
                                         MissingServletRequestParameterException e) {
        LOGGER.error("【{}】发生参数异常:", request.getRequestURL(), e);
        return DataResponse.fail(CommonError.RequestParamsInvalid);
    }

    // 未授权异常.
    @ExceptionHandler(value = AccessDeniedException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request, AccessDeniedException e) {
        LOGGER.error("【{}】发生未授权异常:", request.getRequestURL(), e);
        return DataResponse.fail(CommonError.NotAuthorized);
    }

    // 通用异常.
    @ExceptionHandler(value = AppException.class)
    public BaseResponse domainExceptionHandler(HttpServletRequest request, AppException e) {
        LOGGER.error("【{}】domain exception:{}",request.getRequestURL(), e.getMsg(), e);
        if (StringUtils.isEmpty(e.getMsg())) {
            return DataResponse.fail(e.getErrCode());
        }
        return DataResponse.fail(e.getErrCode(), e.getMsg());
    }

    /**
     * 检验异常.
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request,
                                         MethodArgumentNotValidException e) {
        LOGGER.error("【{}】发生检验异常:", request.getRequestURL(), e);
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = this.formatAllErrorMessages(errors);
        return DataResponse.fail(CommonError.RequestParamsInvalid, message);
    }

    private String formatAllErrorMessages(List<ObjectError> errors) {
        StringBuffer errorMsg = new StringBuffer();
        errors.forEach(error ->
                errorMsg.append(error.getDefaultMessage())
        );
        return errorMsg.toString();
    }
}
